import { Graph, Node } from "@antv/x6";
import { AlgoUnitMetadata } from "./algo-unit-metadata";

const nodeSize = {
  width: 120,
  height: 30,
};

export class AlgoUnit extends Node {
  static getMeta(item: AlgoUnitMetadata): Node.Metadata {
    const portItems = [
      ...item.In.map(a => ({ group: 'in', id: a })),
      ...item.Out.map(a => ({ group: 'out', id: a })),
    ];
    return {
      id: item.Id,
      shape: AlgoUnit.shapeName,
      ...nodeSize,
      label: item.Name,
      ports: {
        items: portItems,
      },
      attrs:{
        label:{
          text: item.Name,
        }
      },
      data:{...item}
    };
  }
  static shapeName = "algo-unit";

  updateInPorts(graph: Graph) {
    const minNumberOfPorts = 2;
    const ports = this._getInPorts();
    const usedPorts = this.getUsedInPorts(graph);
    const newPorts = this._getNewInPorts(
      Math.max(minNumberOfPorts - usedPorts.length, 1)
    );

    if (ports.length === minNumberOfPorts &&
      ports.length - usedPorts.length > 0) {
      // noop
    } else if (ports.length === usedPorts.length) {
      this.addPorts(newPorts);
    } else if (ports.length + 1 > usedPorts.length) {
      this.prop(
        ['ports', 'items'],
        this._getOutPorts().concat(usedPorts).concat(newPorts),
        {
          rewrite: true,
        }
      );
    }

    return this;
  }
  private _getInPorts() {
    return this.getPortsByGroup('in');
  }
  private _getOutPorts() {
    return this.getPortsByGroup('out');
  }
  getUsedInPorts(graph: Graph) {
    const incomingEdges = graph.getIncomingEdges(this) || [];
    return incomingEdges.map((edge) => {
      const portId = edge.getTargetPortId()!;
      return this.getPort(portId);
    });
  }
  private _getNewInPorts(length: number) {
    return Array.from({ length }, () => {
      return { group: 'in' };
    });
  }
}


AlgoUnit.config({
  width: 150,
  height: 40,
  markup: [
    {
      tagName: "rect",
      selector: "body"
    },
    {
      tagName: "text",
      selector: "label"
    }
  ],
  ports: {
    items: [
    ],
    groups: {
      in: {
        position: {
          name: 'left',
        },
        attrs: {
          portBody: {
            magnet: 'passive',
            r: 3,
            stroke: '#5F95FF',
            fill: '#fff',
            strokeWidth: 1,
            tag: "ABC"
          },
        },
      },
      out: {
        position: {
          name: 'right',
        },
        attrs: {
          portBody: {
            magnet: true,
            r: 3,
            fill: '#fff',
            stroke: '#5F95FF',
            strokeWidth: 1,
          },
        },
      },
    },
  },
  portMarkup: [
    {
      tagName: 'circle',
      selector: 'portBody',
    },
  ],
  attrs: {
    root: {
      magnet: false,
    },
    body: {
      refWidth: "100%",
      refHeight: "100%",
      stroke: "#5F95FF",
      fill: "#EFF4FF",
      class: "default",
      rx: 4,
      ry: 4,
    },
    label: {
      refX: 0.5,
      refY: 0.5,
      textAnchor: "middle",
      textVerticalAnchor: "middle",
    }
  }
});